#!/usr/bin/env python

import sys
import ConfigParser
import MySQLdb
import cPickle
sys.path.append('../../modules/sincronizacion/')
from ClinicHistory import *
from Person import *
from Soap import *
from Sincronizacion import *  

from M2Crypto import SSL as SSL_LIB

HOST = '127.0.0.1'
PORT = 5050
BACKLOG = 5
BUFF_SIZE = 1024

SSL_PATH = '../../modules/sincronizacion/certificados/'

SSL_VERSION = 'sslv3'
SSL_CERT_CLI = 'certificado-cliente.pem'
SSL_KEY_CLI = 'clave-cliente.pem'
SSL_CERT_AUTH = 'CAXplotacert.pem'

BD_CONFIG = '../../modules/sincronizacion/settings_client.ini'

class SSL:
	""" Objeto que me proporciona
		la conexion segura con SSL"""

	def __init__(self):
		self.ssl_path = SSL_PATH
		self.ssl_version = SSL_VERSION
		self.ssl_cert_cli = SSL_CERT_CLI
		self.ssl_key_cli = SSL_KEY_CLI
		self.ssl_cert_auth = SSL_CERT_AUTH

	def context(self):
		con = SSL_LIB.Context(self.ssl_version)
		con.load_cert(certfile = self.ssl_path + self.ssl_cert_cli, 
				keyfile = self.ssl_path + self.ssl_key_cli,
				callback = self.pp_callback)
		con.load_verify_locations(self.ssl_path + self.ssl_cert_auth)
		con.set_verify(SSL_LIB.verify_peer | 
				SSL_LIB.verify_fail_if_no_peer_cert, depth = 9)
		return con

	def pp_callback(self, *args):
	# The passpharase is '0987'.
		return '0987'

class Client:
	""" Objeto que me proporciona
		la conexion con el Servidor 
		GRIDEX """

	def __init__(self, con):
		self.host = HOST
		self.port = PORT
		self.backlog = BACKLOG
		self.buff_size = BUFF_SIZE
		self.con = con

	def conect(self):
		c = SSL_LIB.Connection(self.con)
		c.connect((self.host,self.port))
		if c.get_peer_cert() is not None:
			#print "Cliente: Certificado del Servidor Correcto"
			self.conexion = c
		else:
			#print "Cliente: No se pudo validar el Certificado"
			sys.exit()

	def send(self, data):
		len_data = cPickle.dumps(len(data))
		lenn = len(data)
		self.conexion.send(len_data)
		i = 0
		while lenn > 0:
			self.conexion.send(cPickle.dumps(data[i]))
			i += 1
			lenn -= 1
	
	def recv(self):
		data = self.conexion.read()
		len_info = 0
		if len(data) != 0:
			len_info = cPickle.loads(data)
		list = []
		while len_info > 0:
			data = self.conexion.read()
			list.append(cPickle.loads(data))
			len_info -= 1
		return list

	def recv_ex(self):                                                      
		data = self.conexion.read()
		len_info = 0
		if len(data) != 0:
			len_info = cPickle.loads(data)
		list = []
		while len_info > 0:
			list_temp = []
			tam = self.conexion.read()
			tam = cPickle.loads(tam)
			while tam > 0:
				data = self.conexion.read()
				list_temp.append(cPickle.loads(data))
				tam -= 1
			list.append(tuple(list_temp))
			len_info -= 1
		return list

	def recv_message(self):
		data = self.conexion.read()
		return data

	def send_message(self,string):
		self.conexion.send(string)	

	def close(self):
		self.conexion.close()

class BD:
	""" Conexion con la Base de Datos """

	def __init__(self):
		self.bd_config = BD_CONFIG
		self.bd_names = self.getting_names()

	def getting_names(self):
		cp = ConfigParser.ConfigParser()
		cp.read(self.bd_config)
		return cp

	def conect(self):
		try:
			self.db = MySQLdb.connect(
					host=self.bd_names.get('DATABASE','DB_HOSTNAME'),
					user=self.bd_names.get('DATABASE','DB_USERNAME'),
					passwd=self.bd_names.get('DATABASE','DB_PASSWORD'),
					db=self.bd_names.get('DATABASE','DB_NAME'))
		except MySQLdb.Error, e:
			self.error_message(e)

	def get_real_pid(self, cid):
		try:
			c = self.db.cursor()
 			c.execute("""SELECT pid FROM care_person WHERE nat_id_nr=%s""",
					(cid,))
			return int(c.fetchone()[0]) 
		except MySQLdb.Error, e:
			self.error_message(e)

	def update_sync(self, data):
		try:
			c = self.db.cursor()
			for i in data:
				real_pid = self.get_real_pid(i.get_cedula())
				c.execute("""UPDATE """ + 
						self.bd_names.get('DATABASE','DB_TABLE') +
						""" SET version_sincronizacion=%s,version_actual=%s,
						tipo_historia_clinica=%s, tipo_soap=%s,
						empadronado=%s
						WHERE pid=%s and cedula=%s""",
						(i.get_version_actual(),i.get_version_actual(),
							'No','No',i.get_empadronado(),
							real_pid,i.get_cedula()),)
		except MySQLdb.Error, e:
			self.error_message(e) 

	def update_clin_hist(self, data, regs):
		try:
			if len(data) > 0:
				c = self.db.cursor()
				for i in regs:
					real_pid = self.get_real_pid(i.get_cedula())
					c.execute("""DELETE FROM 
							care_historia_datos_historia_clinica 
							WHERE id_paciente=%s """,
							(real_pid),)
				for i in regs:
					list_to_insert = self.get_list_hist(data,i)
					c.executemany("""INSERT INTO 
						care_historia_datos_historia_clinica 
						VALUES (%s,%s,%s,%s,%s)""",list_to_insert)
		except MySQLdb.Error, e:
			self.error_message(e)

	def update_soap(self, data, regs):
		try:
			if len(data) > 0:
				c = self.db.cursor()
				for i in regs:
					real_pid = self.get_real_pid(i.get_cedula())
					c.execute("""DELETE FROM 
						    care_historia_soap	
							WHERE id_paciente=%s """,
							(real_pid),)
				for i in regs:
					list_to_insert = self.get_list_soap(data,i)
					c.executemany("""INSERT INTO 
						care_historia_soap
						VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)""",
						list_to_insert)
		except MySQLdb.Error, e:
			self.error_message(e)
	
	def update_person(self, data):                                          
		try:
			if len(data) > 0:
				c = self.db.cursor()
				list_to_insert = self.get_list_person(data)
				c.executemany("""INSERT INTO care_person
					VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,
							%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,
							%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,
							%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,
							%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,
							%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,
							%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,
							%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)""",
							list_to_insert)
		except MySQLdb.Error, e:
			self.error_message(e)

	def get_list_hist(self, info, reg):
		list = []
		for i in info:
			real_pid = self.get_real_pid(reg.get_cedula())
			if i.get_id_paciente() == reg.get_pid():
				list.append((i.get_id_campo(),i.get_valor(),
					real_pid,i.get_id_correlativo(),
					i.get_ficha()))
		return list

	def get_list_soap(self, info, reg):
		list = []
		for i in info:
			real_pid = self.get_real_pid(reg.get_cedula())
			if i.get_id_paciente() == reg.get_pid():
				list.append((0,i.get_fecha(),i.get_nombre_medico(),
					i.get_matricula_medico(),real_pid,
					i.get_clasificacion_medico(),i.get_subjetivo(),
					i.get_objetivo(),i.get_apreciacion(),i.get_planTPR(),
					i.get_tratamiento(),i.get_tipo(),i.get_referido()))
		return list

	def get_list_person(self, info):
		list = []
		for i in info:
			list.append((0,i.get_date_reg(),i.get_name_first(),
				i.get_name_2(),i.get_name_3(),i.get_name_middle(),
				i.get_name_last(),i.get_name_maiden(),i.get_name_others(),
				i.get_date_birth(),i.get_blood_group(),i.get_addr_str(),
				i.get_addr_str_nr(),i.get_addr_zip(),i.get_addr_citytown_nr(),
				i.get_addr_is_valid(),i.get_citizenship(),i.get_phone_1_code(),
				i.get_phone_1_nr(),i.get_phone_2_code(),i.get_phone_2_nr(),
				i.get_cellphone_1_nr(),i.get_cellphone_2_nr(),i.get_fax(),
				i.get_email(),i.get_civil_status(),i.get_sex(),i.get_title(),
				i.get_photo(),i.get_photo_filename(),i.get_ethnic_orig(),
				i.get_org_id(),i.get_sss_nr(),i.get_nat_id_nr(),i.get_religion(),
				i.get_mother_pid(),i.get_father_pid(),i.get_contact_person(),
				i.get_contact_pid(),i.get_contact_relation(),i.get_death_date(),
				i.get_death_encounter_nr(),i.get_death_cause(),i.get_death_cause_code(),
				i.get_date_updade(),i.get_status(),i.get_history(),
				i.get_modify_id(),i.get_modify_time(),i.get_create_id(),
				i.get_create_time(),i.get_relative_name_first(),
				i.get_relative_name_last(),i.get_relative_phone(),
				i.get_birth_country(),i.get_birth_entity(),i.get_birth_town(),
				i.get_birth_city(),i.get_illiterate(),i.get_educational_level(),
				i.get_educational_plan(),i.get_years_approved(),i.get_profession(),
				i.get_occupation(),i.get_sso(),i.get_addr_citytown_name(),
				i.get_addr_locality(),i.get_addr_entity(),i.get_addr_town(),
				i.get_addr_sector(),i.get_addr_house(),i.get_addr_floor(),
				i.get_addr_reference(),i.get_addr_time(),i.get_name_mother(),
				i.get_name_father(),i.get_comments(),i.get_imaging(),
				i.get_cod_estado(),i.get_numero()))
		return list

	def error_message(self, error):
		#print "Cliente: Error conexion con la Base de Datos"
		#print "Error %d: %s" % (error.args[0], error.args[1])
		sys.exit()

	def close(self):
		self.db.close()

def generators_person(options):
	list = []
	for i in options:
		list.append(Person(
			int(i[0]),i[1],i[2],i[3],i[4],i[5],
			i[6],i[7],i[8],i[9],i[10],
			i[11],i[12],i[13],int(i[14]),int(i[15]),
			i[16],i[17],i[18],i[19],i[20],
			i[21],i[22],i[23],i[24],i[25],
			i[26],i[27],i[28],i[29],i[30],
			i[31],i[32],i[33],i[34],int(i[35]),
			int(i[36]),i[37],int(i[38]),i[39],i[40],
			int(i[41]),i[42],i[43],i[44],i[45],
			i[46],i[47],i[48],i[49],i[50],
			i[51],i[52],i[53],i[54],i[55],
			i[56],i[57],i[58],i[59],i[60],
			i[61],i[62],i[63],i[64],i[65],
			i[66],i[67],i[68],i[69],i[70],
			i[71],i[72],i[73],i[74],i[75],
			i[76],i[77],i[78],int(i[79])))
	return list

def gen_person(i):
	return [i.get_pid(),i.get_date_reg(),i.get_name_first(),
				i.get_name_2(),i.get_name_3(),i.get_name_middle(),
				i.get_name_last(),i.get_name_maiden(),i.get_name_others(),
				i.get_date_birth(),i.get_blood_group(),i.get_addr_str(),
				i.get_addr_str_nr(),i.get_addr_zip(),i.get_addr_citytown_nr(),
				i.get_addr_is_valid(),i.get_citizenship(),i.get_phone_1_code(),
				i.get_phone_1_nr(),i.get_phone_2_code(),i.get_phone_2_nr(),
				i.get_cellphone_1_nr(),i.get_cellphone_2_nr(),i.get_fax(),
				i.get_email(),i.get_civil_status(),i.get_sex(),i.get_title(),
				i.get_photo(),i.get_photo_filename(),i.get_ethnic_orig(),
				i.get_org_id(),i.get_sss_nr(),i.get_nat_id_nr(),i.get_religion(),
				i.get_mother_pid(),i.get_father_pid(),i.get_contact_person(),
				i.get_contact_pid(),i.get_contact_relation(),i.get_death_date(),
				i.get_death_encounter_nr(),i.get_death_cause(),i.get_death_cause_code(),
				i.get_date_updade(),i.get_status(),i.get_history(),
				i.get_modify_id(),i.get_modify_time(),i.get_create_id(),
				i.get_create_time(),i.get_relative_name_first(),
				i.get_relative_name_last(),i.get_relative_phone(),
				i.get_birth_country(),i.get_birth_entity(),i.get_birth_town(),
				i.get_birth_city(),i.get_illiterate(),i.get_educational_level(),
				i.get_educational_plan(),i.get_years_approved(),i.get_profession(),
				i.get_occupation(),i.get_sso(),i.get_addr_citytown_name(),
				i.get_addr_locality(),i.get_addr_entity(),i.get_addr_town(),
				i.get_addr_sector(),i.get_addr_house(),i.get_addr_floor(),
				i.get_addr_reference(),i.get_addr_time(),i.get_name_mother(),
				i.get_name_father(),i.get_comments(),i.get_imaging(),
				i.get_cod_estado(),i.get_numero()]
		
def reciving(cli):
	data = cli.recv_message()
	if data == "0":
		return 0
	else:
		return 1

def sending(cli,list):
	cli.send_message(list)


if __name__ == "__main__":
	ssl = SSL()
	context = ssl.context()
	client = Client(context)
	client.conect()
	try:
# Conexion a la base de datos
		bd = BD()
		bd.conect()
	
		if len(sys.argv) > 1:
			sending(client,sys.argv[1])
			if (reciving(client)):
				reg_info_sync = client.recv()	
				reg_info_person = client.recv_ex()
				reg_info_hist = client.recv()
				reg_info_soap = client.recv()
				reg_list_info_person = generators_person(reg_info_person)
				bd.update_person(reg_list_info_person)
				bd.update_clin_hist(reg_info_hist,reg_info_sync)
				bd.update_soap(reg_info_soap,reg_info_sync)
				bd.update_sync(reg_info_sync)
			else:
				print "No se encontro el registro"
				bd.close()
				client.close()
				sys.exit(1)
		else:
			print "Debe colocar el nombre registro a buscar"
			sys.exit(1)

		bd.close()
		client.close()
		print "1"
	except KeyboardInterrupt:
		print "Keyboard Interrupt recieved"
		client.close()
